home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
a86v400.zip
/
TCOLS.8
< prev
next >
Wrap
Text File
|
1994-01-31
|
17KB
|
405 lines
;---------------
; TCOLS
;---------------
JMP TCOLS
DEFAULT MACRO
DEFT_#1 EQU #2
DB ' (default #2)',0D,0A
#EM
DOC_MSG:
DB 0D,0A
DB 'TCOLS V1.1 Copr.1994 Eric Isaacson, 416 E. Univ.St., BMG IN 47401',0D,0A
DB ' Permission to use granted only to registered A86 users.',0D,0A,0D,0A
DB 'TCOLS converts single-column input into paged, multi-column output.',0D,0A
DB 'Usage: TCOLS <in >out #1 #2 #3 #4 #5 , where',0D,0A
DB ' #1 is the number of major columns you want each page split into',0D,0A
DB ' #2 is the number of lines to skip between each page'
DEFAULT SKIPCT,6
DB ' #3 is the number of chars per line the printer is now set to'
DEFAULT PWIDTH,80
DB ' #4 is the number of lines per page the printer is now set to'
DEFAULT LPAGE,66
DB ' #5 is which line within the first page the printer is now at'
DEFAULT LSTART,0
DB 0D,0A
DB 'Examples:',0D,0A
DB 'TCOLS <MYPROG.XRF >PRN 4 6 96 88',0D,0A
DB ' sends the file MYPROG.XRF to the printer, split into 4 columns, where'
DB 0D,0A
DB ' the printer is set to 96 characters a line, 8 lines per inch.',0D,0A
DB 'TCOLS <NARROW.LST 6 0 80 23 22 | MORE',0D,0A
DB ' provides 6-column screen-paged output.',0D,0A
DB 'NOTE for readability, TCOLS will convert underscores to hyphens when the'
DB 0D,0A
DB ' lines per page is greater than 80.',0D,0A
DOC_LEN EQU $-DOC_MSG
DATA SEGMENT
BUF:
DB 04000 DUP (?)
OUTBUF:
DB 02000 DUP (?)
OUTBUF_LIM:
DB 0100 DUP (?)
DW ? ; in case the line-overflow logic scans back
SOURCE_BUF:
DB 04002 DUP (?)
WIDTH DW ? ; number of characters in an major output column
NCOLS DB ? ; number of major output columns on a page
LPAGE DB ? ; total number of lines on a page (including skipped)
PWIDTH DW ? ; total width in characters of a printed page
BUFEND DW ? ; pointer reached when a buffered page is complete
SKIPCT DB ? ; number of lines skipped between pages
LSTART DB ? ; number of first-page lines already output before program
THISPAGE DB ? ; number of printed lines on this page
DATA ENDS
MAIN:
TCOLS:
CALL SCAN_ARGS ; scan the command arguments
CALL READ_SOURCE ; read the first block of source text
JZ >L2 ; exit if there was no source text
L1: ; loop here for each page of output
CALL GATHER_PAGE ; input a page, and arrange in into columns
PUSHF ; save Z-flag, to see if there is more input
CALL OUTPUT_PAGE ; process the columns-buffer into final output
CALL OFLUSH ; flush the output buffer
POPF ; restore Z flag, is there more output?
JNZ L1 ; loop if there is more output
L2:
JMP GOOD_EXIT ; all done, go back to operating system
; CHECK_DIGIT sees if there is another command-tail argument pointed to by
; SI. If there is, it had better start with a decimal digit, or else we
; abort the program. We return NZ if there is an argument; Z if there are
; no more arguments (terminator 0FF is seen).
CHECK_DIGIT:
PUSH AX ; preserve register across call
L1: ; loop here to skip over blanks and control chars
LODSB ; load the next character
CMP AL,' ' ; is it a blank or control char?
JBE L1 ; loop if yes, to skip the character
DEC SI ; retreat SI back to the first argument-char
CMP AL,0FF ; is it the command-tail terminator?
JE >L2 ; return Z if yes
SUB AL,'0' ; reduce first character to 0--9 range if digit
CMP AL,10 ; is the character a digit?
JAE >E1 ; abort the program if not; NZ is set if yes
L2:
POP AX ; restore clobbered register
RET
E1: ; improper command tail in program invocation
MOV DX,DOC_MSG ; point to the documentation-message
MOV CX,DOC_LEN ; load size of message
JMP ERROR_EXIT ; educate the user about this program
; CLEAR_PAGE calculates the number of lines to be printed on the coming
; page, at sets up a blank columns-buffer based on that number. We return
; with DI pointing just beyond the blanked buffer. If the calculations
; indicate something is wrong, we abort the program.
CLEAR_PAGE:
MOV AL,LPAGE ; fetch the total number of lines on a page
SUB AL,SKIPCT ; subtract the number of lines that we skip
JBE E1 ; abort if we skip more lines than there are
SUB AL,LSTART ; also subtract any first-page lines already output
JBE E1 ; abort if that subtraction has exhausted the count
MOV THISPAGE,AL ; store as the number of lines on this page
MOV LSTART,0 ; cancel first-page count for the subsequent pages
MOV CX,PWIDTH ; load the number of characters per line
MUL CL ; calculate the number of characters in the columns buffer
XCHG CX,AX ; swap the count into CX for blanking
MOV DI,BUF ; point DI to the start of the columns buffer
MOV AL,' ' ; we will fill the buffer with blanks
REP STOSB ; buffer is filled, DI points beyond the buffer
RET
; SCAN_ARGS scans the decimal arguments in the command tail at DS:080. All the
; appropriate page-size variables are set according to these argument values.
SCAN_ARGS:
MOV SI,080 ; point to the command-tail buffer in the PSP
LODSB ; load the size of the command tail
CBW ; extend the size AL to AX
XCHG BX,AX ; swap the size into BX, for indexing
MOV B[BX+SI],0FF ; mark the end of the command-tail with terminator 0FF
CALL CHECK_DIGIT ; any there any arguments in the command tail?
JZ E1 ; abort the program if there are not
CALL SCAN_DECIMAL ; input the first argument-- number of major columns
MOV NCOLS,AL ; store it
XCHG BX,AX ; also swap NCOLS into BL for later calculations
MOV AL,DEFT_SKIPCT; load the default number of lines skipped
CALL SCAN_DECIMAL ; read the next argument if there is any
MOV SKIPCT,AL ; store the number of lines to skip between pages
MOV AL,DEFT_PWIDTH; load the default page width
CALL SCAN_DECIMAL ; read the next argument if there is any
MOV CL,AL ; store in CL for the moment
DIV BL ; divide by major columns count, to get chars per column
SUB CL,AH ; subtract remainder from page width, insures even multiple
MOV AH,0 ; zero out the remainder
MOV WIDTH,AX ; store the number of characters in an output column
CMP AL,2 ; this width had better be at least 2 chars
JB E1 ; abort the program if not
MOV AL,CL ; AX is now the characters-per-line
MOV PWIDTH,AX ; store the characters-per-line printer is set to
MOV AX,CX ; re-fetch the characters-per-line
ADD AX,BUF ; calculate beyond-first-line, reached when buffer full
MOV BUFEND,AX ; store the value for later use
MOV AL,DEFT_LPAGE ; load defualt lines-per-page
CALL SCAN_DECIMAL ; read the next argument, if there is any
MOV LPAGE,AL ; store the total number of lines on a printed page
MOV AL,DEFT_LSTART; load the default first-line-position
CALL SCAN_DECIMAL ; read the next argument, if any
MOV LSTART,AL ; store the starting first-page position
RET
; GATHER_PAGE takes input text at DS:SI, and formats it into columns on a
; single page, at BUF. RZ if the input file end (0FFH marker) was seen.
GATHER_PAGE:
CALL CLEAR_PAGE ; blank-fill the columns-buffer
MOV BX,DI ; point BX beyond the columns-buffer
MOV BP,DX,DI,BUF ; start BP=column ptr DX=line ptr DI=char ptr
L1: ; loop here for each column entry
CALL GATHER_LINE ; copy an input line to a column entry
JZ RET ; return if there is no more input
CALL NEXT_LINE ; advance pointers to the next column entry
JB L1 ; loop if there is another entry on this page
OR AL,0FF ; page complete: set NZ to signal more input
RET
; NEXT_LINE sets DI to the next line of this column in the page display buffer.
; It moves to the top of the next column as necessary. RAE if the page is
; full.
NEXT_LINE:
ADD DX,PWIDTH ; advance column-poi